home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / swmathbx.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  7KB  |  296 lines

  1. /*****************************************************************
  2. machine\swmathbx.c
  3.  
  4. This file is Copyright 1997, Steve Baines.
  5.  
  6. Release 2.0 (5 August 1997)
  7.  
  8. See drivers\starwars.c for notes
  9.  
  10. ******************************************************************/
  11.  
  12. #include "driver.h"
  13. #include "swmathbx.h"
  14.  
  15. #define NOP           0x00
  16. #define LAC           0x01
  17. #define READ_ACC      0x02
  18. #define M_HALT        0x04
  19. #define INC_BIC       0x08
  20. #define CLEAR_ACC     0x10
  21. #define LDC           0x20
  22. #define LDB           0x40
  23. #define LDA           0x80
  24.  
  25. #define MATHDEBUG 0
  26.  
  27. static int MPA; /* PROM address counter */
  28. static int BIC; /* Block index counter  */
  29.  
  30. static int PRN; /* Pseudo-random number */
  31.  
  32.  
  33. /* Store decoded PROM elements */
  34. static int PROM_STR[1024]; /* Storage for instruction strobe only */
  35. static int PROM_MAS[1024]; /* Storage for direct address only */
  36. static int PROM_AM[1024]; /* Storage for address mode select only */
  37.  
  38. void init_starwars(void)
  39. {
  40.     int cnt,val;
  41.     unsigned char *RAM = memory_region(REGION_CPU1);
  42.  
  43.     for (cnt=0;cnt<1024;cnt++)
  44.     {
  45.         /* Translate PROMS into 16 bit code */
  46.         val = 0;
  47.         val = ( val | (( RAM[0x0c00+cnt]     ) & 0x000f ) ); /* Set LS nibble */
  48.         val = ( val | (( RAM[0x0800+cnt]<< 4 ) & 0x00f0 ) );
  49.         val = ( val | (( RAM[0x0400+cnt]<< 8 ) & 0x0f00 ) );
  50.         val = ( val | (( RAM[0x0000+cnt]<<12 ) & 0xf000 ) ); /* Set MS nibble */
  51.  
  52.         /* Perform pre-decoding */
  53.         PROM_STR[cnt] = (val>>8) & 0x00ff;
  54.         PROM_MAS[cnt] =  val     & 0x007f;
  55.         PROM_AM[cnt]  = (val>>7) & 0x0001;
  56.    }
  57. }
  58.  
  59. void init_swmathbox (void)
  60. {
  61.     MPA = BIC = 0;
  62.     PRN = 0;
  63. }
  64.  
  65. void run_mbox(void)
  66. {
  67.     static short ACC, A, B, C;
  68.  
  69.     int RAMWORD=0;
  70.     int MA_byte;
  71.     int tmp;
  72.     int M_STOP=100000; /* Limit on number of instructions allowed before halt */
  73.     int MA;
  74.     int IP15_8, IP7, IP6_0; /* Instruction PROM values */
  75.  
  76.     unsigned char *RAM = memory_region(REGION_CPU1);
  77.  
  78. logerror("Running Mathbox...\n");
  79.  
  80.     while (M_STOP>0)
  81.     {
  82.         IP15_8 = PROM_STR[MPA];
  83.         IP7    = PROM_AM[MPA];
  84.         IP6_0  = PROM_MAS[MPA];
  85.  
  86. #if(MATHDEBUG==1)
  87. printf("\n(MPA:%x), Strobe: %x, IP7: %d, IP6_0:%x\n",MPA, IP15_8, IP7, IP6_0);
  88. printf("(BIC: %x), A: %x, B: %x, C: %x, ACC: %x\n",BIC,A,B,C,ACC);
  89. #endif
  90.  
  91.         /* Construct the current RAM address */
  92.         if (IP7==0)
  93.         {
  94.             MA = ((IP6_0 & 3) | ( (BIC & 0x01ff) <<2) ); /* MA10-2 set to BIC8-0 */
  95.         }
  96.         else
  97.         {
  98.             MA = IP6_0;
  99.         }
  100.  
  101.  
  102.         /* Convert RAM offset to eight bit addressing (2kx8 rather than 1k*16)
  103.         and apply base address offset */
  104.  
  105.         MA_byte=0x5000+(MA<<1);
  106.  
  107.         RAMWORD=( (RAM[MA_byte+1]&0x00ff) | ((RAM[MA_byte]&0x00ff)<<8) );
  108.  
  109. logerror("MATH ADDR: %x, CPU ADDR: %x, RAMWORD: %x\n", MA, MA_byte, RAMWORD);
  110.  
  111.         /*
  112.          * RAMWORD is the sixteen bit Math RAM value for the selected address
  113.          * MA_byte is the base address of this location as seen by the main CPU
  114.          * IP is the 16 bit instruction word from the PROM. IP7_0 have already
  115.          * been used in the address selection stage
  116.          * IP15_8 provide the instruction strobes
  117.          */
  118.  
  119.         /* 0x01 - LAC */
  120.         if (IP15_8 & LAC)
  121.             ACC = RAMWORD;
  122.  
  123.         /* 0x02 - READ_ACC */
  124.         if (IP15_8 & READ_ACC)
  125.         {
  126.             RAM[MA_byte+1] = (ACC & 0x00ff);
  127.             RAM[MA_byte  ] = (ACC & 0xff00) >> 8;
  128.         }
  129.  
  130.         /* 0x04 - M_HALT */
  131.         if (IP15_8 & M_HALT)
  132.             M_STOP = 0;
  133.  
  134.         /* 0x08 - INC_BIC */
  135.         if (IP15_8 & INC_BIC)
  136.             BIC = (++BIC) & 0x1ff; /* Restrict to 9 bits */
  137.  
  138.         /* 0x10 - CLEAR_ACC */
  139.         if (IP15_8 & CLEAR_ACC)
  140.             ACC = 0;
  141.  
  142.         /* 0x20 - LDC */
  143.         if (IP15_8 & LDC)
  144.         {
  145.             C = RAMWORD;
  146.             /* TODO: this next line is accurate to the schematics, but doesn't seem to work right */
  147.             /* ACC=ACC+(  ( (long)((A-B)*C) )>>14  ); */
  148.             /* round the result - this fixes bad trench vectors in Star Wars */
  149.             ACC = ACC+(  ( (((long)((A-B)*C) )>>13)+1)>>1  );
  150.         }
  151.  
  152.         /* 0x40 - LDB */
  153.         if (IP15_8 & LDB)
  154.             B = RAMWORD;
  155.  
  156.         /* 0x80 - LDA */
  157.         if (IP15_8 & LDA)
  158.             A = RAMWORD;
  159.  
  160.         /*
  161.          * Now update the PROM address counter
  162.          * Done like this because the top two bits are not part of the counter
  163.          * This means that each of the four pages should wrap around rather than
  164.          * leaking from one to another.  It may not matter, but I've put it in anyway
  165.          */
  166.         tmp = MPA;
  167.         tmp ++;
  168.         MPA = (MPA&0x0300)|(tmp&0x00ff); /* New MPA value */
  169.  
  170.         M_STOP --; /* Decrease count */
  171.     }
  172. }
  173.  
  174. /******************************************************/
  175. /****** Other Starwars Math related handlers **********/
  176.  
  177. READ_HANDLER( prng_r )
  178. {
  179. #if(MATHDEBUG==1)
  180. printf("prng\n");
  181. #endif
  182.     PRN = (int)((PRN+0x2364)^2); /* This is a total bodge for now, but it works!*/
  183.     return (PRN & 0xff);    /* ASG 971002 -- limit to a byte; the 6809 code cares */
  184. }
  185.  
  186. /********************************************************/
  187. WRITE_HANDLER( prngclr_w )
  188. {
  189. #if(MATHDEBUG==1)
  190. printf("prngclr\n");
  191. #endif
  192.     PRN=0;
  193. }
  194.  
  195. /********************************************************/
  196. WRITE_HANDLER( mw0_w )
  197. {
  198. #if(MATHDEBUG==1)
  199. printf("mw0: %x\n",data);
  200. #endif
  201.     MPA=(data<<2); /* Set starting PROM address */
  202.     run_mbox();   /* and run the Mathbox */
  203. }
  204.  
  205. /********************************************************/
  206. /* BIC - write high bit */
  207. WRITE_HANDLER( mw1_w )
  208. {
  209. #if(MATHDEBUG==1)
  210. printf("mw1: %x\n",data);
  211. #endif
  212.     BIC = (BIC & 0x00ff) | ((data & 0x01)<<8);
  213. }
  214.  
  215. /********************************************************/
  216. /* BIC - write low byte */
  217. WRITE_HANDLER( mw2_w )
  218. {
  219. #if(MATHDEBUG==1)
  220. printf("mw2: %x\n",data);
  221. #endif
  222.     BIC = (BIC & 0x0100) | data;
  223. }
  224.  
  225. /*********************************************************/
  226.  
  227. /*******************************************************/
  228. /*   Divider handlers                                  */
  229. /*******************************************************/
  230.  
  231. static int RESULT;    /* ASG 971002 */
  232. static int DIVISOR, DIVIDEND;
  233.  
  234. /********************************************************/
  235. READ_HANDLER( reh_r )
  236. {
  237.     return((RESULT & 0xff00)>>8 );
  238. }
  239. /********************************************************/
  240. READ_HANDLER( rel_r )
  241. {
  242.     return(RESULT & 0x00ff);
  243. }
  244. /********************************************************/
  245.  
  246.  
  247. WRITE_HANDLER( swmathbx_w )
  248. {
  249.     data &= 0xff;    /* ASG 971002 -- make sure we only get bytes here */
  250.     switch(offset)
  251.     {
  252.       case 0:
  253.         mw0_w(0,data);
  254.         break;
  255.  
  256.       case 1:
  257.         mw1_w(0,data);
  258.         break;
  259.  
  260.       case 2:
  261.         mw2_w(0,data);
  262.         break;
  263.  
  264.       case 4: /* dvsrh */
  265.         DIVISOR = ((DIVISOR & 0x00ff) | (data<<8));
  266.         break;
  267.  
  268.       case 5: /* dvsrl */
  269.  
  270.         /* Note: Divide is triggered by write to low byte.  This is */
  271.         /*       dependant on the proper 16 bit write order in the  */
  272.         /*       6809 emulation (high bytes, then low byte).        */
  273.         /*       If the Tie fighters look corrupt, he byte order of */
  274.         /*       the 16 bit writes in the 6809 are backwards        */
  275.  
  276.         DIVISOR = ((DIVISOR & 0xff00) | (data));
  277.  
  278.         if (DIVIDEND >= 2*DIVISOR)
  279.             RESULT = 0x7fff;
  280.         else
  281.             RESULT = (int)((((long)DIVIDEND<<14)/(long)DIVISOR));
  282.         break;
  283.  
  284.       case 6: /* dvddh */
  285.         DIVIDEND = ((DIVIDEND & 0x00ff) | (data<<8));
  286.         break;
  287.  
  288.       case 7: /* dvddl */
  289.         DIVIDEND = ((DIVIDEND & 0xff00) | (data));
  290.         break;
  291.  
  292.       default:
  293.         break;
  294.     }
  295. }
  296.